/**
 * 融合 axios 和 wepy 部分功能
 * */
import util from "./util";
import $cache from "../wxCache";

class InterceptorManager {
  constructor() {
    this.handlers = [];
  }

  use(fulfilled, rejected) {
    this.handlers.push({
      fulfilled: fulfilled,
      rejected: rejected
    });
    return this.handlers.length - 1;
  }

  forEach(fn) {
    this.handlers.forEach(h => {
      if (h !== null) {
        fn(h);
      }
    })
  }
}

const defaults = {};
defaults.header = {
  common: {
    'Accept': 'application/json, text/plain, */*'
  }
};

class WxRequest {
  constructor(config) {
    this.defaults = util.$merge(defaults, config);
    this.interceptors = {
      request: new InterceptorManager(),
      response: new InterceptorManager()
    };
  }

  request(obj) {
    obj = this.transfor(obj);
    var chain = [(obj) => {return this.promiseRequest(obj)}, undefined];
    var promise = Promise.resolve(obj);

    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
      chain.unshift(interceptor.fulfilled, interceptor.rejected);
    });
    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
      chain.push(interceptor.fulfilled, interceptor.rejected);
    });
    while (chain.length) {
      promise = promise.then(chain.shift(), chain.shift());
    }
    return promise;
  }

  post(obj) {
    obj = obj || {};
    obj = (typeof (obj) === 'string') ? {url: obj} : obj;
    obj.method = "POST";
    if (obj.params) {
      let params = Object.keys(obj.params).map(function (key) {
        return encodeURIComponent(key) + "=" + encodeURIComponent(obj.params[key]);
      }).join("&");
      if (obj.url.indexOf("?") === -1) {
        obj.url = obj.url + "?" + params
      } else {
        obj.url = obj.url + "&" + params
      }
    }
    return this.request(obj)
  }

  get(obj) {
    obj = obj || {};
    obj = (typeof (obj) === 'string') ? {url: obj} : obj;
    obj.method = "GET";
    if (obj.params && !obj.data) {
      obj.data = obj.params;
    }
    return this.request(obj);
  }

  delete(obj) {
    obj = obj || {};
    obj = (typeof (obj) === 'string') ? {url: obj} : obj;
    obj.method = "DELETE";
    return this.request(obj);
  }

  put(obj) {
    obj = obj || {};
    obj = (typeof (obj) === 'string') ? {url: obj} : obj;
    obj.method = "PUT";
    return this.request(obj);
  }

  // 转化为promise
  promiseRequest(obj) {
    return new Promise((resolve, reject) => {
      ['fail', 'success', 'complete'].forEach((k) => {
        obj[k] = (res) => {
          res['__request__'] = {
            url: obj.url,
            ignoreError: obj.ignoreError,
            header: obj.header,
          }
          if (k === 'success') {
            resolve(res);
          } else if (k === 'fail')
            reject(res);
        };
      });
      wx.request(obj)
    });
  }

  transfor(obj) {
    obj = obj || {};
    obj = (typeof (obj) === 'string') ? {url: obj} : obj;

    if (this.defaults.baseUrl && !util.isAbsoluteURL(obj.url)) {
      obj.url = util.combineURLs(this.defaults.baseUrl, obj.url)
    }
    obj.method = obj.method.toUpperCase();
    obj.header = obj.header || {};
    obj.enableHttp2 = true;
    obj.header = util.$merge(
        this.defaults.header.common || {},
        this.defaults.header[obj.method.toLowerCase()] || {},
        obj.header || {}
    );
    return obj;
  }
}

export default WxRequest;
